bitkeeper revision 1.1236.43.1 (4242f75e6Zk-5XZxY7UL-J_Qi8D43g)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 24 Mar 2005 17:22:38 +0000 (17:22 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 24 Mar 2005 17:22:38 +0000 (17:22 +0000)
Fix VIRQ_TIMER holdoff for SMP guests.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
xen/arch/ia64/patch/linux-2.6.7/time.c
xen/arch/x86/time.c
xen/common/sched_atropos.c
xen/common/sched_bvt.c
xen/common/sched_rrobin.c
xen/common/schedule.c
xen/include/xen/sched-if.h
xen/include/xen/sched.h
xen/include/xen/time.h

index 92610b2356984cdac6dd28d193e25c43c5203bf1..d0dec7f85f6a1bdef86945c8fa47894f9b0511d3 100644 (file)
@@ -672,6 +672,7 @@ int set_timeout_timer(void)
 {
        u64 alarm = 0;
        int ret = 0;
+       unsigned long j;
 #ifdef CONFIG_SMP
        unsigned long seq;
 #endif
@@ -685,13 +686,14 @@ int set_timeout_timer(void)
 #ifdef CONFIG_SMP
        do {
                seq = read_seqbegin(&xtime_lock);
-               if (smp_processor_id())
-                       alarm = __jiffies_to_st(jiffies + 1);
-               else
-                       alarm = __jiffies_to_st(jiffies + 1);
+               j = jiffies + 1;
+               alarm = __jiffies_to_st(j);
        } while (read_seqretry(&xtime_lock, seq));
 #else
-       alarm = __jiffies_to_st(next_timer_interrupt());
+       j = next_timer_interrupt();
+       if (j < (jiffies + 1))
+               j = jiffies + 1;
+       alarm = __jiffies_to_st(j);
 #endif
 
        /* Failure is pretty bad, but we'd best soldier on. */
@@ -726,7 +728,6 @@ void time_resume(void)
 }
 
 #ifdef CONFIG_SMP
-#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
 
 static irqreturn_t local_timer_interrupt(int irq, void *dev_id,
                                         struct pt_regs *regs)
@@ -764,11 +765,6 @@ static irqreturn_t local_timer_interrupt(int irq, void *dev_id,
 #endif
        }
 
-       if (smp_processor_id() == 0) {
-           xxprint("bug bug\n");
-           BUG();
-       }
-
        return IRQ_HANDLED;
 }
 
index d0b421fb67f04e6d38d089152110a9801c325933..cf77d6905a6866c511c051827a2cbb0aa210252e 100644 (file)
 +    return now; 
 +}
 +
-+int update_dom_time(struct exec_domain *ed)
++void update_dom_time(struct exec_domain *ed)
 +{
 +// FIXME: implement this?
 +//    printf("update_dom_time: called, not implemented, skipping\n");
-+      return 0;
++      return;
 +}
 +
 +/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
index 208945ca3390d2c4a4a1031b70019c9da406bdfa..2ad8395446012cdc628e680b00146c0fc4fdde14 100644 (file)
@@ -296,18 +296,16 @@ static inline void __update_dom_time(struct exec_domain *ed)
     spin_unlock(&d->time_lock);
 }
 
-int update_dom_time(struct exec_domain *ed)
+void update_dom_time(struct exec_domain *ed)
 {
     unsigned long flags;
 
-    if ( ed->domain->shared_info->tsc_timestamp == full_tsc_irq )
-        return 0;
-
-    read_lock_irqsave(&time_lock, flags);
-    __update_dom_time(ed);
-    read_unlock_irqrestore(&time_lock, flags);
-
-    return 1;
+    if ( ed->domain->shared_info->tsc_timestamp != full_tsc_irq )
+    {
+        read_lock_irqsave(&time_lock, flags);
+        __update_dom_time(ed);
+        read_unlock_irqrestore(&time_lock, flags);
+    }
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
index ec24c03fe2edb8e93e9f5128e4cddc7647124c63..9b7c071b165d203017641a58db9be209f5205753 100644 (file)
@@ -325,7 +325,7 @@ static void block(struct domain* sdom)
 /**
  * ATROPOS - main scheduler function
  */
-task_slice_t ksched_scheduler(s_time_t time)
+struct task_slice ksched_scheduler(s_time_t time)
 {
     struct domain *cur_sdom = current;  /* Current sdom           */
     s_time_t       newtime;
@@ -335,7 +335,7 @@ task_slice_t ksched_scheduler(s_time_t time)
     struct at_dom_info *cur_info;
     static unsigned long waitq_rrobin = 0;
     int i;
-    task_slice_t ret;
+    struct task_slice ret;
 
 
     cur_info = DOM_INFO(cur_sdom);
index 3b91b2a9abcf3e2f8d4646c8cdee425e48829430..65fa6125bff9b188c997e33d5da178c92c8b39bf 100644 (file)
@@ -363,7 +363,7 @@ static int bvt_adjdom(
  *   i.e., the domain with lowest EVT.
  *   The runqueue should be ordered by EVT so that is easy.
  */
-static task_slice_t bvt_do_schedule(s_time_t now)
+static struct task_slice bvt_do_schedule(s_time_t now)
 {
     struct domain *d;
     struct exec_domain      *prev = current, *next = NULL, *next_prime, *ed; 
@@ -375,7 +375,7 @@ static task_slice_t bvt_do_schedule(s_time_t now)
     struct bvt_edom_info *p_einf          = NULL;
     struct bvt_edom_info *next_einf       = NULL;
     struct bvt_edom_info *next_prime_einf = NULL;
-    task_slice_t        ret;
+    struct task_slice     ret;
 
     ASSERT(prev->ed_sched_priv != NULL);
     ASSERT(prev_einf != NULL);
index cfc30c11a1286e940e26eb0bac9a838e48e7dcb8..a3535ae12845aee90994b81378bcf3a697b23dcc 100644 (file)
@@ -99,11 +99,11 @@ static int rr_init_idle_task(struct domain *d)
 }
 
 /* Main scheduling function */
-static task_slice_t rr_do_schedule(s_time_t now)
+static struct task_slice rr_do_schedule(s_time_t now)
 {
     struct domain *prev = current;
     int cpu = current->processor;
-    task_slice_t ret;
+    struct task_slice ret;
     
     if ( !is_idle_task(prev) )
     {
index 562daa6132538b1ae5248f239fa17a397bcef5e5..761f636a75be714af6af96460660069b43fffd1b 100644 (file)
  *
  */
 
+/*#define WAKE_HISTO*/
+/*#define BLOCKTIME_HISTO*/
+
+#if defined(WAKE_HISTO)
+#define BUCKETS 31
+#elif defined(BLOCKTIME_HISTO)
+#define BUCKETS 200
+#endif
+
 #include <xen/config.h>
 #include <xen/init.h>
 #include <xen/lib.h>
 static char opt_sched[10] = "bvt";
 string_param("sched", opt_sched);
 
-/*#define WAKE_HISTO*/
-/*#define BLOCKTIME_HISTO*/
-
-#if defined(WAKE_HISTO)
-#define BUCKETS 31
-#elif defined(BLOCKTIME_HISTO)
-#define BUCKETS 200
-#endif
-
 #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
 
 /*
@@ -66,7 +66,7 @@ static void t_timer_fn(unsigned long unused);
 static void dom_timer_fn(unsigned long data);
 
 /* This is global for now so that private implementations can reach it */
-schedule_data_t schedule_data[NR_CPUS];
+struct schedule_data schedule_data[NR_CPUS];
 
 extern struct scheduler sched_bvt_def;
 // extern struct scheduler sched_rrobin_def;
@@ -371,7 +371,7 @@ void __enter_scheduler(void)
     struct exec_domain *prev = current, *next = NULL;
     int                 cpu = prev->processor;
     s_time_t            now;
-    task_slice_t        next_slice;
+    struct task_slice   next_slice;
     s32                 r_time;     /* time for new dom to run */
 
     perfc_incrc(sched_run);
@@ -446,9 +446,15 @@ void __enter_scheduler(void)
 
     TRACE_2D(TRC_SCHED_SWITCH, next->domain->id, next);
 
+    prev->sleep_tick = schedule_data[cpu].tick;
+
     /* Ensure that the domain has an up-to-date time base. */
-    if ( !is_idle_task(next->domain) && update_dom_time(next) )
-        send_guest_virq(next, VIRQ_TIMER);
+    if ( !is_idle_task(next->domain) )
+    {
+        update_dom_time(next);
+        if ( next->sleep_tick != schedule_data[cpu].tick )
+            send_guest_virq(next, VIRQ_TIMER);
+    }
 
     context_switch(prev, next);
 }
@@ -468,7 +474,7 @@ int idle_cpu(int cpu)
  * - dom_timer: per domain timer to specifiy timeout values
  ****************************************************************************/
 
-/* The scheduler timer: force a run through the scheduler*/
+/* The scheduler timer: force a run through the scheduler */
 static void s_timer_fn(unsigned long unused)
 {
     TRACE_0D(TRC_SCHED_S_TIMER_FN);
@@ -476,20 +482,26 @@ static void s_timer_fn(unsigned long unused)
     perfc_incrc(sched_irq);
 }
 
-/* Periodic tick timer: send timer event to current domain*/
+/* Periodic tick timer: send timer event to current domain */
 static void t_timer_fn(unsigned long unused)
 {
-    struct exec_domain *ed = current;
+    struct exec_domain *ed  = current;
+    unsigned int        cpu = ed->processor;
 
     TRACE_0D(TRC_SCHED_T_TIMER_FN);
 
-    if ( !is_idle_task(ed->domain) && update_dom_time(ed) )
+    schedule_data[cpu].tick++;
+
+    if ( !is_idle_task(ed->domain) )
+    {
+        update_dom_time(ed);
         send_guest_virq(ed, VIRQ_TIMER);
+    }
 
     page_scrub_schedule_work();
 
-    t_timer[ed->processor].expires = NOW() + MILLISECS(10);
-    add_ac_timer(&t_timer[ed->processor]);
+    t_timer[cpu].expires = NOW() + MILLISECS(10);
+    add_ac_timer(&t_timer[cpu]);
 }
 
 /* Domain timer function, sends a virtual timer interrupt to domain */
@@ -498,7 +510,8 @@ static void dom_timer_fn(unsigned long data)
     struct exec_domain *ed = (struct exec_domain *)data;
 
     TRACE_0D(TRC_SCHED_DOM_TIMER_FN);
-    (void)update_dom_time(ed);
+    
+    update_dom_time(ed);
     send_guest_virq(ed, VIRQ_TIMER);
 }
 
index f73eace25b9d72a823a8f141252390158c1691c8..c9fdd23702dc8801fe1cbae80e557079dbd21d16 100644 (file)
@@ -1,36 +1,31 @@
-#include <asm/types.h>
-
-/*
+/******************************************************************************
  * Additional declarations for the generic scheduler interface.  This should
  * only be included by files that implement conforming schedulers.
  *
  * Portions by Mark Williamson are (C) 2004 Intel Research Cambridge
  */
 
-#define BUCKETS 10
+#ifndef __XEN_SCHED_IF_H__
+#define __XEN_SCHED_IF_H__
 
-typedef struct schedule_data_st
-{
-    spinlock_t          schedule_lock;  /* spinlock protecting curr pointer
-                                            TODO check this */
-    struct exec_domain  *curr;          /* current task */
-    struct exec_domain  *idle;          /* idle task for this cpu */
-    void *              sched_priv;
-    struct ac_timer     s_timer;        /* scheduling timer  */
+struct schedule_data {
+    spinlock_t          schedule_lock;  /* spinlock protecting curr        */
+    struct exec_domain *curr;           /* current task                    */
+    struct exec_domain *idle;           /* idle task for this cpu          */
+    void               *sched_priv;
+    struct ac_timer     s_timer;        /* scheduling timer                */
+    unsigned long       tick;           /* current periodic 'tick'         */
 #ifdef BUCKETS
     u32                 hist[BUCKETS];  /* for scheduler latency histogram */
 #endif
-} __cacheline_aligned schedule_data_t;
-
+} __cacheline_aligned;
 
-typedef struct task_slice_st
-{
+struct task_slice {
     struct exec_domain *task;
     s_time_t            time;
-} task_slice_t;
+};
 
-struct scheduler
-{
+struct scheduler {
     char *name;             /* full name for this scheduler      */
     char *opt_name;         /* option name for this scheduler    */
     unsigned int sched_id;  /* ID for this scheduler             */
@@ -44,7 +39,7 @@ struct scheduler
     void         (*sleep)          (struct exec_domain *);
     void         (*wake)           (struct exec_domain *);
     void         (*do_block)       (struct exec_domain *);
-    task_slice_t (*do_schedule)    (s_time_t);
+    struct task_slice (*do_schedule) (s_time_t);
     int          (*control)        (struct sched_ctl_cmd *);
     int          (*adjdom)         (struct domain *,
                                     struct sched_adjdom_cmd *);
@@ -53,7 +48,6 @@ struct scheduler
     int          (*prn_state)      (int);
 };
 
-/* per CPU scheduler information */
-extern schedule_data_t schedule_data[];
-
+extern struct schedule_data schedule_data[];
 
+#endif /* __XEN_SCHED_IF_H__ */
index 44f24831e86d8ff0fdec316422ed14fdd6a1b38c..861f1a24a0e2351badd4ca771996c4fa22402b8c 100644 (file)
@@ -73,6 +73,7 @@ struct exec_domain
 #endif
 
     struct ac_timer  timer;         /* one-shot timer for timeout values */
+    unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
 
     s_time_t         lastschd;      /* time this domain was last scheduled */
     s_time_t         lastdeschd;    /* time this domain was last descheduled */
index b1eeade753e06dea257db1f484236ebd1502df6d..104b6112127e6914c5de6e1ecea8097e5c16892a 100644 (file)
@@ -54,9 +54,9 @@ s_time_t get_s_time(void);
 #define MILLISECS(_ms)  (((s_time_t)(_ms)) * 1000000ULL )
 #define MICROSECS(_us)  (((s_time_t)(_us)) * 1000ULL )
 
-extern int update_dom_time(struct exec_domain *ed);
-extern void do_settime(unsigned long secs, unsigned long usecs, 
-                       u64 system_time_base);
+extern void update_dom_time(struct exec_domain *ed);
+extern void do_settime(
+    unsigned long secs, unsigned long usecs, u64 system_time_base);
 
 #endif /* __XEN_TIME_H__ */